﻿#include <string.h>
#include <stdlib.h>
#include "FileIO.h"
//#define MODE_TSCN_STR "tscn"
//#define MODE_TSCN_BY_ANIM_STR "tscn_by_anim"
//#define MODE_ANIM_TRES_STR "anim_tres"

#include "PvzReanim.h"

void FileOpen(FILE** fp, const char* filename, const char* mode, int exit_code)
{
	//printf("filename = %s mode = %s\n", filename, mode);
	errno_t err = fopen_s(fp, filename, mode);
	if (err != 0 || *fp == NULL)
	{
		fprintf(stderr, "%s = NULL return code = %d\n", filename, exit_code);
		exit(exit_code);
	}
}
void FileClose(FILE* fp)
{
	if (fp!= NULL)
		fclose(fp);
}

void FileRead(FILE* input, char* filetext)
{
	for (int i = 0; (filetext[i] = fgetc(input)) != EOF; i++);
}

void _FileWritePvzTrack(FILE* output, Tracks* track, int times)
{
	fprintf(output, "tracks/%d/type = \"%s\"\n", track->num, track->type);
	fprintf(output, "tracks/%d/imported = %s\n", track->num, track->imported ? "true" : "false");
	fprintf(output, "tracks/%d/enabled = %s\n", track->num, track->enabled ? "true" : "false");
	fprintf(output, "tracks/%d/path = NodePath(\"%s\")\n", track->num, track->path);
	fprintf(output, "tracks/%d/interp = %d\n", track->num, track->interp);
	fprintf(output, "tracks/%d/loop_wrap = %s\n", track->num, track->loop_wrap ? "true" : "false");
	fprintf(output, "tracks/%d/keys = {\n", track->num);
	fprintf(output, "\"times\": PackedFloat32Array(");
	for (int i = 0; i < times; i++)
	{
		fprintf(output, "%f", track->key.times[i]);
		if (i != times - 1)
		{
			fprintf(output, ", ");
		}
	}
	fprintf(output, "),\n");
	fprintf(output, "\"transitions\": PackedFloat32Array(");
	for (int i = 0; i < times; i++)
	{
		fprintf(output, "%f", track->key.transitions[i]);
		if (i != times - 1)
		{
			fprintf(output, ", ");
		}
	}
	fprintf(output, "),\n");
	fprintf(output, "\"update\": %d,\n", track->key.update);
	fprintf(output, "\"values\": [");
	for (int i = 0; i < times; i++)
	{
		fprintf(output, "%s", track->key.values[i]);
		if (i != times - 1)
		{
			fprintf(output, ", ");
		}
	}
	fprintf(output, "]\n");
	fprintf(output, "}\n");
}

void FileWriteTracks(PVZAnimation* anim, const bool is_bm_enabled)
{
	FILE* output = anim->fp_third_output_track;
	_FileWritePvzTrack(output, anim->tracks->tracks_vis, anim->current_tracks_vis_key_times);
	_FileWritePvzTrack(output, anim->tracks->tracks_pos, anim->current_tracks_pos_key_times);
	_FileWritePvzTrack(output, anim->tracks->tracks_rot, anim->current_tracks_rot_key_times);
	_FileWritePvzTrack(output, anim->tracks->tracks_scale, anim->current_tracks_scale_key_times);
	_FileWritePvzTrack(output, anim->tracks->tracks_skew, anim->current_tracks_skew_key_times);
	_FileWritePvzTrack(output, anim->tracks->tracks_texture, anim->current_tracks_texture_key_times);
	_FileWritePvzTrack(output, anim->tracks->tracks_alpha, anim->current_tracks_alpha_key_times);
	if (is_bm_enabled)
		_FileWritePvzTrack(output, anim->tracks->tracks_blendmode, anim->current_tracks_blendmode_key_times);
	fflush(output);
}

void FileMergeFiles(FILE* output_file, const char* output_type, FILE* input_files[], int num_files)
{
	fprintf_s(output_file, "; Generated by PVZ_reanim2godot_animation v%s\n\n", VERSION);
	if (strcmp(output_type, "tscn") == 0)
	{
		fprintf_s(output_file, "[gd_scene load_steps=114 format=4 uid=\"fuck_uid_114514_1919810\"]\n\n");
	}
	else if (strcmp(output_type, "tres") == 0)
	{
		fprintf_s(output_file, "[gd_resource type=\"Animation\" format=3 uid=\"fuck_uid_1919810_114514\"]\n\n");
	}
	else
	{
		fprintf(stderr, "Unknown output type %s\n", output_type);
		fprintf(stderr, "如果你遇到了这个错误，请立刻联系开发者并提供错误信息！错误代码：0x004f\n");
	}
	for (int i = 0; i < num_files; i++) {
		FILE* input_file = input_files[i];
		if (input_file == NULL) {
			fprintf(stderr, "Input file %d is NULL\n", i);
			continue;
		}
		// 重置输入文件指针到文件开头
		fseek(input_file, 0, SEEK_SET);

		int ch;
		while ((ch = fgetc(input_file)) != EOF)
		{
			fputc(ch, output_file);
		}
	}
}

void FileGetFileName(const char* fileWholePath, char* fileName)
{
	// 使用strrchr()函数查找最后一个目录分隔符
	const char* fileName_linux = strrchr(fileWholePath, '/');
	const char* fileName_windows = strrchr(fileWholePath, '\\');
	const char* filename = fileName_linux > fileName_windows ? fileName_linux : fileName_windows;

	// 如果找到了分隔符，则文件名在分隔符之后
	if (filename)
	{
		filename++;  // 跳过分隔符
	}
	else
	{
		// 如果未找到分隔符，则整个路径就是文件名
		filename = fileWholePath;
	}
	for (int i = 0; i < NAME_LENTH; i++)
	{
		fileName[i] = filename[i] == '.' ? '\0' : filename[i];
	}
}

void FileGetFilePath(const char* fileWholePath, char* filePath)
{
	// 使用strrchr()函数查找最后一个目录分隔符
	const char* filePath_linux = strrchr(fileWholePath, '/');
	const char* filePath_windows = strrchr(fileWholePath, '\\');
	const char* filepath = filePath_linux > filePath_windows ? filePath_linux : filePath_windows;

	// 如果找到了分隔符，则文件路径在分隔符之前
	if (filepath)
	{
		for (int i = 0; i <= filepath - fileWholePath; i++)
		{
			filePath[i] = fileWholePath[i];
		}
		filePath[filepath - fileWholePath + 1] = '\0';
	}
	else
	{
		// 如果未找到分隔符，则整个路径就是文件路径
		strcpy_s(filePath, NAME_LENTH, ".");
	}
}


void FileExtResource(PVZAnimation* pvz_anim[], int anim_index, int anim_num, const char* anim_godot_path, const char* res_godot_path, const bool is_bm_enabled, const bool is_ext_anim_enabled)
{
	fprintf_s(pvz_anim[anim_index]->fp_first_output_ext, "; Generated by PVZ_reanim2godot_animation v%s\n\n", VERSION);
	if (is_bm_enabled)
	{
		fprintf_s(pvz_anim[anim_index]->fp_first_output_ext, "[ext_resource type=\"Shader\" path=\"res://normal.gdshader\" id=\"normal_shader\"]\n");
		fprintf_s(pvz_anim[anim_index]->fp_first_output_ext, "[ext_resource type=\"Shader\" path=\"res://add.gdshader\" id=\"add_shader\"]\n");
	}
	for (int i = 0; i < pvz_anim[anim_index]->filename_fuck_times; i++)
	{
		fprintf_s(pvz_anim[anim_index]->fp_first_output_ext, "[ext_resource type=\"Texture2D\" path=\"%s%s\" id=\"%d_fuck\"]\n", res_godot_path, pvz_anim[anim_index]->filename_fuck[i], i);
	}
	fprintf_s(pvz_anim[anim_index]->fp_first_output_ext, "\n");
	if (strcmp(pvz_anim[anim_index]->output_file_extension, "tscn"/*MODE_TSCN_STR*/) == 0 && is_ext_anim_enabled)
	{
		for (int i = 1; i <= anim_num; i++)
		{
			if (i == anim_index)
			{
				continue;
			}
			fprintf_s(pvz_anim[anim_index]->fp_first_output_ext, "[ext_resource type=\"Animation\" path=\"%s%s.tres\" id=\"%d_anim\"]\n", anim_godot_path, pvz_anim[i]->ResName, i);
		}
		fprintf_s(pvz_anim[anim_index]->fp_first_output_ext, "\n");
	}
	
	if (is_bm_enabled)
	{
		fprintf_s(pvz_anim[anim_index]->fp_first_output_ext, "[sub_resource type=\"ShaderMaterial\" id=\"ShaderMaterial_normal\"]\nshader = ExtResource(\"normal_shader\")\n\n");
		fprintf_s(pvz_anim[anim_index]->fp_first_output_ext, "[sub_resource type=\"ShaderMaterial\" id=\"ShaderMaterial_add\"]\nshader = ExtResource(\"add_shader\")\n\n");
	}
	fflush(pvz_anim[anim_index]->fp_first_output_ext);
}

void FileSetAnim(FILE* output, const char* output_type, const char* ResName, int time_num)
{
	fprintf_s(output, "; Generated by PVZ_reanim2godot_animation v%s\n\n", VERSION);
	if (strcmp(output_type, "tres"/*MODE_ANIM_TRES_STR*/) == 0)
	{
		fprintf_s(output, "[resource]\nresource_name = \"%s\"\n", ResName);

	}
	else // strcmp(output_type, tscn MODE_TSCN_BY_ANIM_STR) == 0
	{
		fprintf_s(output, "[sub_resource type=\"Animation\" id=\"Animation_fuck\"]\n");
	}
	fprintf_s(output, "length = %.6Lf\n", (float)(time_num - 1) * (1.0 / FPS));
	fprintf_s(output, "step = %.6Lf\n", 1.0 / FPS);
	fflush(output);
}

void FileAddNode(FILE* output, const int tracks_num, const int anim_num, const char node_name[MAX_TEXTURE_NUM][NAME_LENTH], PVZAnimation* pvz_anim[], const bool is_ext_anim_enabled)
{
	fprintf_s(output, "; Generated by PVZ_reanim2godot_animation v%s\n\n", VERSION);
	fprintf_s(output, "[sub_resource type=\"AnimationLibrary\" id=\"AnimationLibrary_fuck\"]\n_data = {\n\"ALL_ANIMS\": SubResource(\"Animation_fuck\")\n}\n\n");
	for (int i = 1; i <= anim_num && is_ext_anim_enabled; i++)
	{
		fprintf_s(output, "[sub_resource type=\"AnimationLibrary\" id=\"AnimationLibrary_%s\"]\n", pvz_anim[i]->ResName);
		fprintf_s(output, "_data = {\n");
		fprintf_s(output, "&\"%s\": ExtResource(\"%d_anim\")\n", pvz_anim[i]->ResName, i);
		fprintf_s(output, "}\n");
	}
	fprintf_s(output, "[node name=\"Node2D\" type=\"Node2D\"]\n\n");
	for (int i = 0; i < tracks_num; i++)
	{
		fprintf_s(output, "[node name=\"%s\" type=\"Sprite2D\" parent=\".\"]\n", node_name[i]);
		fprintf_s(output, "centered = false\n\n");
	}
	fprintf_s(output, "[node name=\"AnimLib\" type=\"AnimationPlayer\" parent=\".\"]\nlibraries = {\n\"\": SubResource(\"AnimationLibrary_fuck\")\n}\n\n");
	for (int i = 1; i <= anim_num && is_ext_anim_enabled; i++)
	{
		fprintf_s(output, "[node name=\"Anim_%s\" type=\"AnimationPlayer\" parent=\".\"]\nlibraries = {\n\"\": SubResource(\"AnimationLibrary_%s\")\n}\n\n", pvz_anim[i]->ResName, pvz_anim[i]->ResName);
	}
	fflush(output);
}
